#include <iostream>
// https://www.jianshu.com/p/77c2988be336
// !!!无法复制unique_ptr对象，它只能移动
// release() 只是释放所有权，没有 delete 原始指针，其返回值不接着会造成内存泄漏
// explicit const noexcept
// swap -> &&=
// 模板内部不需要写明 <T>
template<class T>
class unique_ptr{
private:
    T* _ptr;

public:
    explicit unique_ptr(T* ptr = nullptr): _ptr(ptr) {}
    unique_ptr(const unique_ptr& up) = delete;
    unique_ptr(const unique_ptr&& up) noexcept: _ptr(up._ptr) {up._ptr = nullptr;}
    ~unique_ptr(){
        if(_ptr != nullptr) delete _ptr;
    }

    unique_ptr& operator=(const unique_ptr& up) = delete;
    unique_ptr& operator=(unique_ptr&& up) noexcept{
        std::swap(_ptr, up._ptr);
        return *this;
    }

public:
    T& operator*() const noexcept{ return *_ptr;}
    T* operator->() const noexcept{ return _ptr;}
    explicit operator bool() const noexcept{ return _ptr == nullptr;}

public:
    T* get() const noexcept{ return _ptr; };

    T* release(){
        T* tmp = _ptr;
        _ptr = 0;
        return tmp;
    }

    void reset(T* q = nullptr) noexcept{
        if(q == _ptr) return;
        if(_ptr) delete _ptr;
        _ptr = q;
    }
};